package org.budo.dubbo.protocol.async;

import org.budo.dubbo.protocol.async.repository.AbstractAsyncRepository;
import org.budo.dubbo.protocol.async.repository.AsyncRepository;
import org.budo.dubbo.protocol.async.util.RepositoryUtil;
import org.budo.support.spring.context.aware.BudoApplicationContextAware;
import org.budo.support.spring.util.SpringUtil;

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcResult;

/**
 * 发消息
 * 
 * @author lmw
 */
public class BudoAsyncDubboInvoker<T> implements Invoker<T> {
    private static final Logger log = LoggerFactory.getLogger(BudoAsyncDubboInvoker.class);

    private Class<T> interfaceType;

    private URL url;

    private AsyncRepository _asyncRepository;

    public BudoAsyncDubboInvoker(Class<T> interfaceType, URL url) {
        this.url = url;
        this.interfaceType = interfaceType;
    }

    /**
     * 代理接口方法被调用时，发送消息
     */
    @Override
    public Result invoke(Invocation invocation) throws RpcException {
        AsyncRepository asyncRepository = this.asyncRepository();
        asyncRepository.sendMessageWhenInvoke(invocation);
        return new RpcResult();
    }

    @Override
    public boolean isAvailable() {
        String asyncRepositoryBeanName = RepositoryUtil.getAsyncRepositoryBeanName(this);

        return null != BudoApplicationContextAware.getBean(asyncRepositoryBeanName);
    }

    @Override
    public URL getUrl() {
        return this.url;
    }

    @Override
    public Class<T> getInterface() {
        return this.interfaceType;
    }

    @Override
    public void destroy() {
        log.info("#67 destroy, this=" + this);
    }

    private AsyncRepository asyncRepository() {
        if (null != this._asyncRepository) {
            return this._asyncRepository;
        }

        String beanName = RepositoryUtil.getAsyncRepositoryBeanName(this);
        AbstractAsyncRepository asyncRepository = (AbstractAsyncRepository) SpringUtil.getBeanCached(beanName);

        if (null != asyncRepository) {
            return this._asyncRepository = asyncRepository;
        }

        // 还没准备好?
        log.error("#84 asyncRepository=" + asyncRepository + ", beanName=" + beanName + ", this=" + this);
        return null;
    }

    @Override
    public String toString() {
        return super.toString() //
                + ", interface=" + this.getInterface() //
                + ", url=" + this.getUrl();
    }
}